import java.io.BufferedReader;
import java.io.IOException;
import java.net.Socket;
import java.io.*;
import java.net.*;
import java.util.Random;



public class PlayerConnected extends Thread {

	BufferedReader BR;
	Socket clientsocket;
	InputStreamReader IR;
	BufferedWriter OS;
	int id;
	Server server;
	
	/*Variables responisble for information like:
	 * stack of the player,is he a dealer now,is he has a turn 
	 * if he is being activ player(fold or check,...)
	 */
	public boolean dealer = false;
	public int MyStack = 1500;
	public String command ="";
	public boolean MyTurn = false;
	public boolean CARDEX = false;
	public boolean Active = true;
	public boolean ALLIN = false;
	public boolean Alive = true;
	public  Card Hand[] = new Card[4];
	public 	String Message = ""; 
	public 	String[] MS;
	public  String Task;
	public static String[] Exchange = new String[4];
	public  Rank CardRank;
	
	//In play variables Mystack,Min
	public int MIN = 0;
	public int StakeDone;
	public int T;
	public int MyStackPOM = 0;
	
	
	
	
	//--------------------Thread Constructor------------------------//
	public PlayerConnected(Socket clientsocket,int id,Server server){
	
	/*Socket clientsocket-we sent clientsocket created by server for this thread of given id,
	 *We pass also Server which  have one port for listening,and one new port for each connected player.We now can operating on this object.
	 */
	
	this.server = server;
	this.id = id;
	this.clientsocket = clientsocket;
	System.out.println("Connection established with: Player" + id + " clientsocket:" + clientsocket); 
	try {
		IR = new InputStreamReader(this.clientsocket.getInputStream());   //BR used for reading data flowing to the socket
	    BR = new BufferedReader(IR);  //BR.readLine(); used for reading strings from input
	    OS = new BufferedWriter(new OutputStreamWriter(this.clientsocket.getOutputStream()));             
	}catch (IOException e) {
		System.out.println("Error occured while trying to get InputStream");
		} 
	
}
	
//-----------------------------------------RUN_METHOD------------------------------------------//
	
	/*Method run will be running when thread.start() happaned
	 * 
	 */
	
	public void run() {
		System.out.print("Thread is alive");
		int Bet;
		Random rnd = new Random();
		int x;
		
		while(Alive){
			
			if(MyTurn == true || CARDEX == true){
				
				try {
					if(MyTurn){
						OS.write("M,"+MyStack+"," + MIN); //We send M-task, MyStack- Min-which is changing
						OS.newLine();
						OS.flush();
					}
					Message = BR.readLine();
					MS = Message.split(",");
					Task = MS[0];
				
				switch (Task) {
				
				case "FOLD":
					Active = false;
					Server.ActiveLeft = Server.ActiveLeft-1;
					Server.BankUpdate(StakeDone,0,MIN,"Fold",MyStack);
					Server.Moved[T] = 1;
					break;
				case "CALL":
					MyStackPOM = MyStack;
					MyStack = MyStack -MIN+StakeDone;
					if(MyStack <= 0){
						Server.BankUpdate(StakeDone+MyStackPOM,MyStackPOM,MIN,"ALLIN",0);
						ALLIN();
						Active = false;
						MyStack = 0;
						Server.Moved[T] = 1;
						Server.ActiveLeft = Server.ActiveLeft-1;}
					else{
						Server.BankUpdate(MIN,MIN-StakeDone, MIN,"Call",MyStack);
						Server.Moved[T] = 1;
						StakeDone = MIN;}
					break;
				case "ALLIN":
					MyStackPOM = MyStack;
					StakeDone = MyStack+StakeDone;
					if(MyStack<MIN)
						Server.BankUpdate(StakeDone,MyStack,MIN,"ALLIN",0);
					else
						Server.BankUpdate(StakeDone,MyStackPOM , StakeDone,"ALLIN",0);
					ALLIN();
					Active = false;
					MyStack = 0;
					Server.Moved[T] = 1;
					Server.ActiveLeft = Server.ActiveLeft-1;
					break;
				case "BR":
					Bet = Integer.parseInt(MS[1]);
					MyStack = MyStack-Bet;
					Server.BankUpdate(StakeDone + Bet,Bet,Bet+StakeDone,"R/B",MyStack);
					StakeDone = StakeDone + Bet;
					for(int i =0;i<=Server.members-1;i++)
						Server.Moved[i] = 0;
					Server.Moved[T] = 1;
					break;
				case "CHECK":
					Server.BankUpdate(StakeDone,0,MIN,"Check",MyStack);
					Server.Moved[T] = 1;
					break;
				case "E":
					System.out.println("Hand Request Accepted");
					for(int i =1;i<=4;i++)
						Exchange[i-1] = MS[i];
					//System.out.println(": " + Exchange[0]+","+Exchange[1]+","+Exchange[2]+","+Exchange[3]);
					for(int i =0;i<4;i++)
						if(Exchange[i].equals("1")){
							Server.Deck2.add(Hand[i]);
							x=rnd.nextInt(Server.Deck.size());
							Hand[i]=Server.Deck.get(x);
							Server.Deck.remove(x);
							System.out.println("Action on Deck finished");}
					SendHand();
					System.out.println("Hand Sent");
					break;
						
					
				
				}
				CARDEX = false;
				MyTurn = false;
				System.out.println("XXX");
				
				} catch (IOException e) {
					System.out.println("Cannot CleanUp User's GUI to client!");
				}
				
			}
		}
		
		//Client is dead. We need to close thread and sockets.
		 try {
		     OS.write("END");
			 OS.newLine(); 
			 OS.flush();	
			 OS.close();
			 BR.close();
			 clientsocket.close(); 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Player "+ id + " have lost!");
		
	}
	
	//Setting client's turn!!!!!!!!!1
	
	public void InitiateRank(int i){
		CardRank = new Rank(Hand,i);
		CardRank.Resort();
	}
	
	public void Won(int i){
		MyStack = MyStack + i;
	}
	
	public void Check(){
		if(MyStack!=0){
			Active = true;
			ALLIN = false;
			Alive = true;
		}
		else{
			Alive=false;
			Server.Left();}
	}
	
	public void ALLIN(){
		ALLIN = true;
		Server.AllinCount = Server.AllinCount + 1;
	}
	
	//Method responsible for giving turn for exchaning card
	public void E(){
		CARDEX= true;
	}
	
	public void Turn(int M,int e)
	{
		MyTurn = true;      
		MIN = M;   //current minimal stake 
		T = e;    //e is our index 
	}
	
	//We returning if this current player is active.
	public boolean IsActive(){
		return Active;
	}
	
	public boolean IsALLIN(){
		return ALLIN;
	}
	
	public void NotActive()
	{
		Active = false;
	}
	
	//Method for making current player a dealer
	public void Dealer(){
		this.dealer = true;
		System.out.println("Player 1 established as a dealer for a next round");
	}
	//Method for checking if current player is a dealer.
	public boolean IsDealer(){
		if(this.dealer == true)
			return true;
		else
			return false;
	}
	
	//SmallBling taken from player
	public int SmallBLind(){
		MyStack = MyStack - 15;
		StakeDone = 15;
		return 15;
	}
	//Big Blind taken from a player
	public int BigBlind(){
		MyStack = MyStack - 30;
		StakeDone = 30;
		return 30;
	}
	//Card given to the player from dealer(server)
	public void TakeCards(int i,Card c){
		Hand[i] = c;
	}

	
	//Return stack
	public int Stack(){
		return MyStack;
	}
	
	public void SendStack(String S){
		try {
			OS.write(S);
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot CleanUp User's GUI to client!");
		}
	}
	
	//Method responsible for sending information about Players Hand to himself
	public void SendHand(){
		String s = "H,";
		for(int i=0;i<4;i++)
			s=s+Hand[i].CardFigure()+Hand[i].CardColour().charAt(0)+",";
		System.out.println(s);
		System.out.println("LOOOOL");
		try {
			OS.write(s);
			OS.newLine(); //ACHTUNG!!!
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot send message to client!");
		}
	}
	
	
	
	//Getting basic info from server and sending it to stack
	public void SendBasicInfo(int B,int D,int MC,int DC,int T,int BOOL){
		String Info = "B,"+B+","+D+","+MC+","+DC + ","+MyStack+","+ T+"," + BOOL;
	
		try {
			OS.write(Info);
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot send BasicInformation to client!");
		}
	}
	
	public void CleanUp(String S){
		try {
			OS.write(S);
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot CleanUp User's GUI to client!");
		}
	}
	
	public void MovedMade(int i,String S,int B,int M,int Stack){       //we sending to client(G-gui,I-nr,LastMove,MyStack,B-bank
		try {
			OS.write("G,"+i+","+S+","+Stack+","+B+"," + M);
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot Order Player to Moved GUI to client!");
		}
	}

	public void UpdateStack() {
		try {
			OS.write("ST,"+MyStack);
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot UpdateStack to client!");
		}
		
	}
	
	public void DiscardCards() {
		try {
			OS.write("DS");
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Cannot CleanUp User's GUI to client!");
		}
		
	}

	public void Clear() {
		try {
			OS.write("CC");
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Clean UP");
		}
		
	}
	
	public void RoundStake(){
		StakeDone = 0;
		try {
			OS.write("RC");
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Clean UP");
		}
	}

	public void RC() {
		try {
			OS.write("CR");
			OS.newLine(); 
			OS.flush();	
		} catch (IOException e) {
			System.out.println("Clean UP");
		}
	}
	
	
}
